package com.open.capacity.salary.controller;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import com.open.capacity.commons.PageResult;
import com.open.capacity.commons.Result;
import com.open.capacity.salary.dto.GridHeadDataDto;
import com.open.capacity.salary.dto.GridHeadDataDto2;
import com.open.capacity.salary.entity.GzItem;
import com.open.capacity.salary.entity.GzZt;
import com.open.capacity.salary.service.GzEnableMonthService;
import com.open.capacity.salary.service.GzItemService;
import com.open.capacity.salary.service.GzReportService;
import com.open.capacity.salary.service.GzZtService;
import com.open.capacity.utils.StringUtil;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * 报表
 *
 * @author
 * @email
 * @date 2021-08-02 14:26:51
 */
@Slf4j
@RestController
@RequestMapping("gzreports")
@Api(tags = "工资报表")
public class GzReportController {

    @Autowired
    private GzReportService reportService;

    @Autowired
    private GzItemService gzItemService;

    @Autowired
    private GzZtService ztService;

    /**
     * 工资查询列表
     */
    @RequestMapping("/gzmxb/listall")
    public Result gzmxb_listall(@RequestParam Map<String, Object> params) {
        List<Map<String, Object>> list = reportService.findAll(params);
        return Result.succeed(list);
    }


    /**
     * 工资查询表头
     */
    @RequestMapping("/gzmxb/header")
    public Result<GridHeadDataDto> gzmxb_header(@RequestParam Map<String, Object> params) {
        String companyId = params.get("companyId").toString();
        String ztId = params.get("ztId").toString();
        String editable = params.get("editable").toString();

        TreeMap<Integer, GridHeadDataDto.ColData> hsColMap = new TreeMap<>();
        TreeMap<Integer, GridHeadDataDto.ColData2> hsColMap2 = new TreeMap<>();

        GridHeadDataDto data = new GridHeadDataDto();

        List<GridHeadDataDto.ColData> colDatas = new ArrayList<>();
        List<GridHeadDataDto.ColData2> colData2s = new ArrayList<>();
        List<String> colNames = new ArrayList<>();

        GridHeadDataDto.ColData departmentName = new GridHeadDataDto.ColData.Builder().label("部门").name("departmentname").align("center").width(120).sort(true).frozen(true).build();
        GridHeadDataDto.ColData userCode = new GridHeadDataDto.ColData.Builder().label("员工编号").name("usercode").align("center").width(80).sort(true).frozen(true).build();
        GridHeadDataDto.ColData userName = new GridHeadDataDto.ColData.Builder().label("姓名").name("username").align("center").width(120).sort(true).frozen(true).build();
        GridHeadDataDto.ColData month = new GridHeadDataDto.ColData.Builder().label("月份").name("month").align("center").width(60).sort(true).frozen(true).build();
        hsColMap.put(1, departmentName);
        hsColMap.put(2, userCode);
        hsColMap.put(3, userName);
        hsColMap.put(4, month);

        GridHeadDataDto.ColData2 departmentName2 = new GridHeadDataDto.ColData2.Builder().title("部门").field("departmentname").colspan(1).rowspan(1).checked(true).columnId("departmentname").width(104).align("center").build();
        GridHeadDataDto.ColData2 userCode2 = new GridHeadDataDto.ColData2.Builder().title("员工编号").field("usercode").colspan(1).rowspan(1).checked(true).columnId("usercode").width(74).align("center").build();
        GridHeadDataDto.ColData2 userName2 = new GridHeadDataDto.ColData2.Builder().title("姓名").field("username").colspan(1).rowspan(1).checked(true).columnId("username").width(84).align("center").build();
        GridHeadDataDto.ColData2 month2 = new GridHeadDataDto.ColData2.Builder().title("月份").field("month").colspan(1).rowspan(1).checked(true).columnId("month").width(42).align("center").build();
        hsColMap2.put(1, departmentName2);
        hsColMap2.put(2, userCode2);
        hsColMap2.put(3, userName2);
        hsColMap2.put(4, month2);

        int index = 5;

        List<String> itemList = gzItemService.findByZtIds(companyId, ztId);

        GridHeadDataDto.ColData.Builder.Edit edit = new GridHeadDataDto.ColData.Builder.Edit();
        edit.setType("number");
        edit.setChange("function (data, num) { }");

        for (String item : itemList) {
            if (editable.equals("1")) {
                GridHeadDataDto.ColData col = new GridHeadDataDto.ColData.Builder()
                        .label(item)
                        .name(item)
                        .align("right")
                        .statistics(true)
                        .sort(true)
                        .formatter("function (cellvalue) { return $.formatMoney(cellvalue, 2)}")
                        .edit(edit)
                        .width(120).build();
                hsColMap.put(index++, col);
            } else {
                GridHeadDataDto.ColData col = new GridHeadDataDto.ColData.Builder()
                        .label(item)
                        .name(item)
                        .align("right")
                        .statistics(true)
                        .sort(true)
                        .formatter("function (cellvalue) { return $.formatMoney(cellvalue, 2)}")
                        .width(120).build();
                hsColMap.put(index++, col);
            }

            colNames.add(item);

            GridHeadDataDto.ColData2 col2 = new GridHeadDataDto.ColData2.Builder()
                    .title(item)
                    .field(item)
                    .align("right")
                    .colspan(1).rowspan(1).checked(true).columnId(item).width(120).build();
            hsColMap2.put(index++, col2);
        }

        //GridHeadDataDto.ColData description = new GridHeadDataDto.ColData.Builder().label("备注").name("description").align("left").width(100).build();
        GridHeadDataDto.ColData id = new GridHeadDataDto.ColData.Builder().label("id").name("id").align("center").width(1).hidden(true).build();
        //hsColMap.put(index++, description);
        hsColMap.put(index++, id);

        //保证有序
        for (Map.Entry<Integer, GridHeadDataDto.ColData> m : hsColMap.entrySet()) {
            GridHeadDataDto.ColData val = m.getValue();
            colDatas.add(val);
        }

        //保证有序
        for (Map.Entry<Integer, GridHeadDataDto.ColData2> m : hsColMap2.entrySet()) {
            GridHeadDataDto.ColData2 val = m.getValue();
            colData2s.add(val);
        }

        data.setColData(colDatas);
        data.setColData2(colData2s);
        data.setColNames(colNames);
        return Result.succeed(data, "成功");
    }

    /**
     * 工资查询导出
     *
     * @return
     */
    @GetMapping("/gzmxb/exportExcel")
    public void gzmxb_export(@RequestParam Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) {
        String companyId = params.get("companyId").toString();
        String ztIds = params.get("ztId").toString();
        String ztName = ztService.findNameByIds(ztIds);
        String monthStart = params.get("monthStart").toString();
        String monthEnd = params.get("monthEnd").toString();
        String monthName = monthStart + (monthEnd.equals(monthStart) ? "" : ("至" + monthEnd)) + "月";

        //账套当前月份
        //String currentMonth = gzEnableMonthService.findByZtId(companyId, ztId).getCurrentMonth();
        String fileName = ztName + monthName;

        List<Map<String, Object>> resList = reportService.findAll(params);
        //封装表头
        List<ExcelExportEntity> headList = new ArrayList<>();
        ExcelExportEntity excelExportEntity;

        /**
         * name : "姓名"    ---> 表头显示    key是属性映射（后面会用到，key任意配置，但不要在同一个方法中重复）
         * excelExportEntity.setWidth(30);    --->  设置单元格宽度
         * excelExportEntity.setNeedMerge(true);   --->  开启单元格合并，这个属性的开启并不会产生影响，因为没有配置合并条件
         * */

        excelExportEntity = new ExcelExportEntity("部门", "departmentname");
        excelExportEntity.setWidth(15);
        excelExportEntity.setNeedMerge(true);
        excelExportEntity.setMergeVertical(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("员工编号", "usercode");
        excelExportEntity.setWidth(10);
        excelExportEntity.setNeedMerge(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("姓名", "username");
        excelExportEntity.setWidth(12);
        excelExportEntity.setNeedMerge(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("身份证号", "code");
        excelExportEntity.setWidth(20);
        excelExportEntity.setNeedMerge(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("月份", "month");
        excelExportEntity.setWidth(10);
        excelExportEntity.setNeedMerge(true);
        headList.add(excelExportEntity);

        //遍历动态表头
        List<String> itemList = gzItemService.findByZtIds(companyId, ztIds);
        if (params.containsKey("columns") && StringUtils.isNotEmpty(params.get("columns").toString())) { //选择列导出
            List<String> columnList = Arrays.asList(params.get("columns").toString().split(","));
            for (String dynamicCol : itemList) {
                if (columnList.contains(dynamicCol)) {
                    excelExportEntity = new ExcelExportEntity(dynamicCol, dynamicCol);
                    //excelExportEntity.setNumFormat("0.00");
                    excelExportEntity.setType(10);
                    headList.add(excelExportEntity);
                }
            }
        } else {
            for (String dynamicCol : itemList) {
                excelExportEntity = new ExcelExportEntity(dynamicCol, dynamicCol);
                //excelExportEntity.setNumFormat("0.00");
                excelExportEntity.setType(10);
                headList.add(excelExportEntity);
            }
        }

        //"封装"数据
        List<Map<String, Object>> dataList = new ArrayList<>();
        Map<String, Object> dataMap;
        //循环封装数据
        for (Map<String, Object> element : resList) {
            dataMap = new HashMap<>();
            dataMap.put("departmentname", element.get("departmentname"));
            dataMap.put("usercode", element.get("usercode"));
            dataMap.put("username", element.get("username"));
            dataMap.put("code", element.get("code"));
            dataMap.put("month", element.get("month"));

            for (String col : itemList) {
                if (element.containsKey(col)) {
                    dataMap.put(col, element.get(col));
                }
            }
            dataList.add(dataMap);
        }
        //导出
        if (CollectionUtils.isNotEmpty(dataList)) {
            response.setContentType("application/vnd.ms-excel");
            try {
                response.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes(), "ISO8859-1") + ".xls");
            } catch (UnsupportedEncodingException e) {
                log.error(e.toString());
            }
            OutputStream ouputStream = null;
            ExportParams param = new ExportParams(null, monthName);
            Workbook workbook = ExcelExportUtil.exportExcel(param, headList, dataList);
            try {
                ouputStream = response.getOutputStream();
                workbook.write(ouputStream);
            } catch (Exception e) {
                log.error(e.toString());
                throw new RuntimeException("系统异常");
            } finally {
                try {
                    if (ouputStream != null) {
                        ouputStream.flush();
                        ouputStream.close();
                    }
                } catch (Exception e) {
                    log.error(e.toString());
                    throw new RuntimeException("系统异常");
                }
            }
        }
    }

    /**
     * 个人明细表
     */
    @RequestMapping("/grmxb/list")
    public PageResult grmxb_list(@RequestParam Map<String, Object> params) {
        PageResult pageResult = reportService.pageByUser(params);
        return pageResult;
    }

    /**
     * 个人明细表表头
     */
    @RequestMapping("/grmxb/header")
    public Result<GridHeadDataDto> grmxb_header(@RequestParam Map<String, Object> params) {
        String companyId = params.get("companyId").toString();
        String ztId = params.get("ztId").toString();
        String editable = params.get("editable").toString();

        TreeMap<Integer, GridHeadDataDto.ColData> hsColMap = new TreeMap<>();
        TreeMap<Integer, GridHeadDataDto.ColData2> hsColMap2 = new TreeMap<>();

        GridHeadDataDto data = new GridHeadDataDto();

        List<GridHeadDataDto.ColData> colDatas = new ArrayList<>();
        List<GridHeadDataDto.ColData2> colData2s = new ArrayList<>();
        List<String> colNames = new ArrayList<>();

        GridHeadDataDto.ColData departmentName = new GridHeadDataDto.ColData.Builder().label("部门").name("departmentname").align("center").width(120).sort(true).frozen(true).build();
        GridHeadDataDto.ColData userCode = new GridHeadDataDto.ColData.Builder().label("员工编号").name("usercode").align("center").width(80).sort(true).frozen(true).build();
        GridHeadDataDto.ColData userName = new GridHeadDataDto.ColData.Builder().label("姓名").name("username").align("center").width(120).sort(true).frozen(true).build();
        GridHeadDataDto.ColData month = new GridHeadDataDto.ColData.Builder().label("月份").name("month").align("center").width(80).sort(true).frozen(true).build();

        hsColMap.put(1, departmentName);
        hsColMap.put(2, userCode);
        hsColMap.put(3, userName);
        hsColMap.put(4, month);

        GridHeadDataDto.ColData2 departmentName2 = new GridHeadDataDto.ColData2.Builder().title("部门").field("departmentname").colspan(1).rowspan(1).checked(true).columnId("departmentname").width(84).align("center").build();
        GridHeadDataDto.ColData2 userCode2 = new GridHeadDataDto.ColData2.Builder().title("员工编号").field("usercode").colspan(1).rowspan(1).checked(true).columnId("usercode").width(64).align("center").build();
        GridHeadDataDto.ColData2 userName2 = new GridHeadDataDto.ColData2.Builder().title("姓名").field("username").colspan(1).rowspan(1).checked(true).columnId("username").width(64).align("center").build();
        GridHeadDataDto.ColData2 month2 = new GridHeadDataDto.ColData2.Builder().title("月份").field("month").colspan(1).rowspan(1).checked(true).columnId("month").width(46).align("center").build();

        hsColMap2.put(1, departmentName2);
        hsColMap2.put(2, userCode2);
        hsColMap2.put(3, userName2);
        hsColMap2.put(4, month2);

        int index = 5;

        List<String> itemList = gzItemService.findByZtIds(companyId, ztId);

        GridHeadDataDto.ColData.Builder.Edit edit = new GridHeadDataDto.ColData.Builder.Edit();
        edit.setType("number");
        edit.setChange("function (data, num) { }");

        for (String item : itemList) {
            if (editable.equals("1")) {
                GridHeadDataDto.ColData col = new GridHeadDataDto.ColData.Builder()
                        .label(item)
                        .name(item)
                        .align("right")
                        .statistics(true)
                        .sort(true)
                        .formatter("function (cellvalue) { return $.formatMoney(cellvalue, 2)}")
                        .edit(edit)
                        .width(120).build();
                hsColMap.put(index++, col);
            } else {
                GridHeadDataDto.ColData col = new GridHeadDataDto.ColData.Builder()
                        .label(item)
                        .name(item)
                        .align("right")
                        .statistics(true)
                        .sort(true)
                        .formatter("function (cellvalue) { return $.formatMoney(cellvalue, 2)}")
                        .width(120).build();
                hsColMap.put(index++, col);
            }

            colNames.add(item);

            GridHeadDataDto.ColData2 col2 = new GridHeadDataDto.ColData2.Builder()
                    .title(item)
                    .field(item)
                    .colspan(1).rowspan(1).checked(true).columnId(item).width(120).build();
            hsColMap2.put(index++, col2);
        }

        //GridHeadDataDto.ColData description = new GridHeadDataDto.ColData.Builder().label("备注").name("description").align("left").width(100).build();
        GridHeadDataDto.ColData id = new GridHeadDataDto.ColData.Builder().label("id").name("id").align("center").width(1).hidden(true).build();
        //hsColMap.put(index++, description);
        hsColMap.put(index++, id);

        //保证有序
        for (Map.Entry<Integer, GridHeadDataDto.ColData> m : hsColMap.entrySet()) {
            GridHeadDataDto.ColData val = m.getValue();
            colDatas.add(val);
        }

        //保证有序
        for (Map.Entry<Integer, GridHeadDataDto.ColData2> m : hsColMap2.entrySet()) {
            GridHeadDataDto.ColData2 val = m.getValue();
            colData2s.add(val);
        }

        data.setColData(colDatas);
        data.setColData2(colData2s);
        data.setColNames(colNames);
        return Result.succeed(data, "成功");
    }

    /**
     * 个人明细表导出
     *
     * @return
     */
    @GetMapping("/grmxb/exportExcel")
    public void grmxb_export(@RequestParam Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) {
        String companyId = params.get("companyId").toString();
        String ztId = params.get("ztId").toString();
        String ztName = ztService.findNameByIds(ztId);
        if (ztId.contains(",")) {
            ztId = ztId.split(",")[0];
        }
        String fileName = ztName;

        List<Map<String, Object>> resList = reportService.findByUser(params);
        //封装表头
        List<ExcelExportEntity> headList = new ArrayList<>();
        ExcelExportEntity excelExportEntity;

        /**
         * name : "姓名"    ---> 表头显示    key是属性映射（后面会用到，key任意配置，但不要在同一个方法中重复）
         * excelExportEntity.setWidth(30);    --->  设置单元格宽度
         * excelExportEntity.setNeedMerge(true);   --->  开启单元格合并，这个属性的开启并不会产生影响，因为没有配置合并条件
         * */

        excelExportEntity = new ExcelExportEntity("部门", "departmentname");
        excelExportEntity.setWidth(15);
        excelExportEntity.setNeedMerge(true);
        excelExportEntity.setMergeVertical(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("员工编号", "usercode");
        excelExportEntity.setWidth(10);
        excelExportEntity.setNeedMerge(true);
        excelExportEntity.setMergeVertical(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("姓名", "username");
        excelExportEntity.setWidth(12);
        excelExportEntity.setNeedMerge(true);
        excelExportEntity.setMergeVertical(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("身份证号", "code");
        excelExportEntity.setWidth(20);
        excelExportEntity.setNeedMerge(true);
        headList.add(excelExportEntity);

        excelExportEntity = new ExcelExportEntity("月份", "month");
        excelExportEntity.setWidth(10);
        excelExportEntity.setNeedMerge(true);
        headList.add(excelExportEntity);

        //遍历动态表头
        List<GzItem> itemList = gzItemService.findByZtId(companyId, ztId);
        if (params.containsKey("columns") && StringUtils.isNotEmpty(params.get("columns").toString())) { //选择列导出
            List<String> columnList = Arrays.asList(params.get("columns").toString().split(","));
            for (GzItem dynamicCol : itemList) {
                if (columnList.contains(dynamicCol.getName())) {
                    excelExportEntity = new ExcelExportEntity(dynamicCol.getName(), dynamicCol.getName());
                    excelExportEntity.setType(10);
                    //excelExportEntity.setNumFormat("0.00");
                    headList.add(excelExportEntity);
                }
            }
        } else {
            for (GzItem dynamicCol : itemList) {
                excelExportEntity = new ExcelExportEntity(dynamicCol.getName(), dynamicCol.getName());
                excelExportEntity.setType(10);
                //excelExportEntity.setNumFormat("0.00");
                headList.add(excelExportEntity);
            }
        }

        //"封装"数据
        List<Map<String, Object>> dataList = new ArrayList<>();
        Map<String, Object> dataMap;
        //循环封装数据
        for (Map<String, Object> element : resList) {
            dataMap = new HashMap<>();
            dataMap.put("departmentname", element.get("departmentname"));
            dataMap.put("usercode", element.get("usercode"));
            dataMap.put("username", element.get("username"));
            dataMap.put("code", element.get("code"));
            dataMap.put("month", element.get("month"));

            for (GzItem col : itemList) {
                if (element.containsKey(col.getName())) {
                    dataMap.put(col.getName(), element.get(col.getName()));
                }
            }
            dataList.add(dataMap);
        }
        //导出
        if (CollectionUtils.isNotEmpty(dataList)) {
            response.setContentType("application/vnd.ms-excel");
            try {
                response.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes(), "ISO8859-1") + ".xls");
            } catch (UnsupportedEncodingException e) {
                log.error(e.toString());
            }
            OutputStream ouputStream = null;
            ExportParams param = new ExportParams();
            Workbook workbook = ExcelExportUtil.exportExcel(param, headList, dataList);
            try {
                ouputStream = response.getOutputStream();
                workbook.write(ouputStream);
            } catch (Exception e) {
                log.error(e.toString());
                throw new RuntimeException("系统异常");
            } finally {
                try {
                    if (ouputStream != null) {
                        ouputStream.flush();
                        ouputStream.close();
                    }
                } catch (Exception e) {
                    log.error(e.toString());
                    throw new RuntimeException("系统异常");
                }
            }
        }
    }

}
